<?php

/*
 * Copyright 2008 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#namespace tehframework\objects\propertyeditors;

#use tehframework\objects\PropertyEditor;

class BooleanEditor extends PropertyEditor
{
	/**
	 * @var array<string>
	 */
	protected $falseStrings = array('false', 'off', 'no', '0', '');
	
	/**
	 * Create a new BooleanEditor instance.
	 * 
	 * @param string? $falseStrings
	 *        An array of strings that represent boolean FALSE.
	 *        Defaults to 'false', 'off', 'no', '0' and empty string.
	 */
	public function __construct(array $falseStrings = null)
	{
		if ($falseStrings !== null)
		{
			$this->setFalseStrings($falseStrings);
		}
	}
	
	/**
	 * Sets an array of strings that represent boolean FALSE.
	 *
	 * @param  array<string> $falseStrings
	 *         An array of strings that represent boolean FALSE.
	 * @return BooleanEditor
	 */
	public function setFalseStrings(array $falseStrings)
	{
		$this->falseStrings = array();
		
		foreach ($falseStrings as $falseString)
		{
			$this->falseStrings[] = strtolower((string)$falseString);
		}
		
		return $this;
	}
	
	/**
	 * Edits the given property so that it meets this editor's format.
	 * 
	 * Result depends on a type of the given {@link $propertyValue value}:
	 * - string:
	 *   if string is one of those specified in the {@link $falseString}
	 *   property, the result is FALSE, otherwise TRUE.
	 * - object:
	 *   always TRUE.
	 * - array:
	 *   always TRUE.
	 * - null:
	 *   always FALSE.
	 * - boolean:
	 *   just the specified value.
	 * - resource:
	 *   always TRUE.
	 * - integer:
	 *   0 is FALSE, otherwise TRUE.
	 * - float:
	 *   0.0 is FALSE, otherwise TRUE.
	 * 
	 * @param  mixed $propertyValue
	 *         A value to be edited.
	 * @return string
	 *         A {@link $propertyValue value} converted to boolean.
	 */
	public function editProperty($propertyValue)
	{
		switch (gettype($propertyValue))
		{
			case 'object':
			case 'array':
			case 'resource':
				return true;
			
			case 'double':
				return $propertyValue !== (float)0;
			
			case 'integer':
				return $propertyValue !== 0;
			
			case 'boolean':
				return $propertyValue;
			
			case 'string':
			{
				$propertyValue = strtolower(trim($propertyValue));
				
				if (in_array($propertyValue, $this->falseStrings, true))
				{
					return false;
				}
				
				return true;
			}
			
			default:
				return false;
		}
	}
}